//工具模块，为方块操作相关的通用代码

//用来创建一行小方块数据
//cols是一行小方块的个数
function createRow(cols){
    //构造包含cols个元素的数组，并全部填充为0,为空方块
    return new Array(cols).fill(0)
}

//用来创建一个区域的小方块数据
//rows为行数，cols为列数
function createBlock(rows,cols){
    //先准备一个包含rows个元素的数组
    //然后把其中每个元素映射为一行方块的数据
    //map()方法创建一个新数组
    //使用定义的createRow（）创建一行空方块
    return new Array(rows).fill().map(() => createRow(cols))
}

//实现数组元素的“深拷贝”
function deepCopy(blocks,callback){
    //存储的是一个俄罗斯方块数据，用map（）方法
    //创建一个新的俄罗斯方块副本
    //当复制每个小方块的值时都调用callback函数
    //并将小方块的值0/1都传进去
    //如果传入了callback函数，则调用它进行小方块数据的转换，否则，直接返回小方块的原始值
    return blocks.map(row =>row.map(block =>callback ? callback(block):block))
}
//测试功能是否正确
//console.log(createBlock(10,20))

//合并数组
//des：目标区域，可以理解为存储游戏区域小方块状态的二维数组
//src：源数据，可以理解为构成当前俄罗斯方块的小方块的二维数组
//offsetRow：俄罗斯方块所在位置的行坐标
//offsetCol：列坐标
//这个函数是要把两个区块数据的二维数组合并
function merge(des,src,offsetRow,offsetCol){
    //首先，我们依次遍历当前俄罗斯方块的每一行
    for(let r = 0;r < src.length;r++){
        //以及行里面的每一列
        for(let c = 0;c < src[r].length;c++){
            //dr和dc是构成当前俄罗斯方块的每一个小方块将要合并到的位置，对应游戏区域的行，列坐标
            const dr = r +offsetRow, dc = c + offsetCol
            //把组成当前俄罗斯方块的每一个小方块数据覆盖到游戏区域的对应位置
            //满足条件：
            //1.组成俄罗斯方块的小方块在此为止不能是空方块
            //2.合并的目标位置不能越界，也就是不能超出游戏区域的范围
            //3.游戏区域的目标位置必须是空方块
            if(src[r][c] 
                && (dr >= 0 && dr < des.length) 
                && (dc >= 0 && dc < des[dr].length)
                && !des[dr][dc]){
                    des[dr][dc] = src[r][c]
                }

        }
    }
    //最后，把合并的结果返回
    return des
}


//对角线交换
function diagonalSwap(blocks){
  
    for(let r = 0;r < blocks.length;r++){
        for(let c = r + 1;c < blocks[r].length; c++){
           /* const t = blocks[r][c]
            blocks[r][c] = blocks[c][r]
            blocks[c][r] = t*/
            //等价于
             //将blocks中的第r行c列的值和第c行r列的值交换
            [blocks[r][c],blocks[c][r]] = [blocks[c][r],blocks[r][c]]
        }
    }
}

//上下交换
    //将第r行和第3-r行的元素交换
function upDownSwap(blocks){
    for(let r = 0;r < blocks.length / 2; r++){
        //是使用数组的解构赋值语法来进行交换
        [blocks[r],blocks[blocks.length - 1 - r]]
           = [blocks[blocks.length - 1 - r],blocks[r]]
    }

}

//需要接收两个参数
//blocks是要旋转的区块数据，二维数组
//rotate是旋转角度，默认-1是逆时针旋转90度
function rotate(blocks,rotate=-1){
    //abs：绝对值；rotate的绝对值表示旋转几个90度
    for(let i = 0;i < Math.abs(rotate); i++){
        if(rotate > 0){
            //顺时针旋转90度可以等价与先上下对调，再沿主对角线对调
            upDownSwap(blocks)
            diagonalSwap(blocks)
        }else{
            //逆时针旋转90度可以理解为先沿主对角线对调元素的位置，再上下对调
            diagonalSwap(blocks)
            upDownSwap(blocks)
        }
    }
    
}

//将最后定义的函数导出，以便在模块外使用
export default{
    createBlock,
    createRow,
    deepCopy,
    merge,
    rotate
}